#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion

namespace GameStateManagement
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        SpriteFont gameFont;
               
        Vector2 scorePosition = new Vector2(5, 5);
        Vector2 shieldPosition = new Vector2(650, 5);
        Vector2 boostPosition = new Vector2(650, 35); 
        Random random = new Random();

        Player player;
        
        Rectangle shipRect;
        Texture2D ship;
             
        Texture2D shield;

        Texture2D enemyTexture;
        List<Enemy> enemies;

        TimeSpan enemySpawnTime;
        TimeSpan previousSpawnTime;

        //Random random;

        Texture2D projectileTexture;
       public List<projectile> projectiles;
        
        TimeSpan fireTime;
        TimeSpan previousFireTime;

        home1 station;

        float pauseAlpha;
        ScreenManager Screen;
        
        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
            

            player = new Player(); 
            station = new home1();
            enemies = new List<Enemy>();
            shipRect = new Rectangle((int)player.position.X, (int)player.position.Y, 16, 22);

            previousSpawnTime = TimeSpan.Zero;

            enemySpawnTime = TimeSpan.FromSeconds(2.0f);

            projectiles = new List<projectile>();

            fireTime = TimeSpan.FromSeconds(1.0f);
         }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            gameFont = content.Load<SpriteFont>("gamefont");
            ship = content.Load<Texture2D>("ship");
            shield = content.Load<Texture2D>("shieldAni");
            player.setShield(shield); 

            enemyTexture = content.Load<Texture2D>("enemyship");

            projectileTexture = content.Load<Texture2D>("laser");

            Vector2 main_basePosition = new Vector2(ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.X, 
                ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Y + ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Height / 2);

            station.Initialize(content.Load<Texture2D>("main_base"), main_basePosition);
       
            // A real game would probably have more content than this sample, so
            // it would take longer to load. We simulate that by delaying for a
            // while, giving you a chance to admire the beautiful loading screen.
            Thread.Sleep(1000);

            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                // Apply some random jitter to make the enemy move around.
                const float randomization = 10;

                
                // Apply a stabilizing force to stop the enemy moving off the screen.
                Vector2 targetPosition = new Vector2(
                    ScreenManager.GraphicsDevice.Viewport.Width / 2 - gameFont.MeasureString("Insert Gameplay Here").X / 2, 
                    200);

               player.update(gameTime);

               station.Update();
              
               UpdateEnemies(gameTime);
               
               UpdateProjectiles();
                UpdateCollision();
            

                // TODO: this game isn't very fun! You could probably improve
                // it by inserting something more interesting in this space :-)
            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
            {
                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
           

        }
     
        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.Black, 0, 0);

            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            spriteBatch.Begin();

            foreach (Shield s1 in player.shieldList)
                  s1.Draw(spriteBatch); 
                //spriteBatch.Draw(shield, s1.getPos(), s1.getRect(), Color.White, s1.getRot(), new Vector2(2, 2), 1, SpriteEffects.None, 0);

            spriteBatch.Draw(ship, player.position, shipRect, Color.White, player.getRot(), new Vector2(9,12), 1, SpriteEffects.None, 0);
            spriteBatch.DrawString(gameFont, "Score: " + player.getScore(), scorePosition, Color.Green);
            spriteBatch.DrawString(gameFont, "Shields: " + player.getShields(), shieldPosition, Color.Blue);
            spriteBatch.DrawString(gameFont, "Boost: " + (int)player.getBoost(), boostPosition, Color.Red);

            for (int i = 0; i < enemies.Count; i++)
            {
                enemies[i].Draw(spriteBatch);
            }

            for (int i = 0; i < projectiles.Count; i++)
            {
                projectiles[i].Draw(spriteBatch);
            }

            //if (station.base_health <= 0)
            //{
            //    spriteBatch.DrawString(basefont, "GAME OVER!", new Vector2(150, 200), Color.LimeGreen);
            //}
            //spriteBatch.Draw(ship, player.position, Color.White); 
            station.Draw(spriteBatch);
            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }

        private void AddEnemy()
        {
            Animation enemyAnimation = new Animation();

            enemyAnimation.Initialize(enemyTexture, Vector2.Zero, 95, 98, 4, 30, Color.White, 1f, true);
                        
            Vector2 position = new Vector2(ScreenManager.GraphicsDevice.Viewport.Width / 2 + 300,
                ScreenManager.GraphicsDevice.Viewport.Height / 2);

            Enemy enemy = new Enemy();

            enemy.Initialize(enemyAnimation, position);

            enemies.Add(enemy);
        }

        private void UpdateEnemies(GameTime gameTime)
        {
           GameStateManagementGame game = new GameStateManagementGame();
           ScreenManager screen = new ScreenManager(game);
           
            if (enemies.Count < 1)
                AddEnemy();

             for (int i = enemies.Count - 1; i >= 0; i--)
             {
                 if (projectiles.Count == 0 && enemies[i].enemyState == Enemy.EnemyAiState.Attack)
                 {
                     Vector2 left = new Vector2(-1, 0);

                     Matrix rotMatrix = Matrix.CreateRotationZ(enemies[i].GetEnemyOrientation);
                     Vector2 velocity = Vector2.Transform(left, rotMatrix);
                     AddProjectile(enemies[i].Position - new Vector2(enemies[i].Width / 2, 0), velocity * -1.0f, enemies[i].GetEnemyOrientation);
                     enemies[i].enemyState = Enemy.EnemyAiState.Escape;
                 }


                 if (projectiles.Count > 0)
                 {
                     for (int j = projectiles.Count - 1; j >= 0; j--)
                     {
                         enemies[j].Update(gameTime, station.main_basePosition, projectiles[j].Position, screen);
                     }
                 }
                 else
                 {
                     enemies[i].Update(gameTime, station.main_basePosition, Vector2.Zero, screen);
                 }

                 if (enemies[i].Active == false)
                 {
                     enemies.RemoveAt(i);
                 }
             }
            
        }

        private void AddProjectile(Vector2 position, Vector2 heading, float rotation)
        {
            projectile projectile = new projectile();
            projectile.Initialize(ScreenManager.GraphicsDevice.Viewport, projectileTexture, position, heading, rotation);
            projectiles.Add(projectile);
        }

        private void UpdateProjectiles()
        {
            for (int i = projectiles.Count - 1; i >= 0; i--)
            {
                projectiles[i].Update();

                if (projectiles[i].Active == false)
                {
                    projectiles.RemoveAt(i);
                }
            }
        }

        private void UpdateCollision()
        {
            //Use the Rectangle's built-in intersect function to
            //determine if two objects are overlapping
            Rectangle mainBaseRectangle;
            Rectangle projectileRectangle;
            Rectangle enemyRectangle;
            

            //Only create the rectangle once for the player
            mainBaseRectangle = new Rectangle((int)station.main_basePosition.X,
            (int)station.main_basePosition.Y,
            station.Width,
            station.Height);

            
                    //Subtract the health from the player based on
                    //the enemy damage
                    //station.base_health -= projectiles[i].Damage;

                    //Since the enemy collided with the player
                    // destroy it
                    //projectiles[i].Health = 0;

                    //If the player health is less than zero we died
                    //if (station.base_health <= 0)
                    //    station.Active = false;
                
            
            //Do the collision between the projectile and the main base
            for (int i = 0; i < projectiles.Count; i++)
            {
                projectileRectangle = new Rectangle((int)projectiles[i].Position.X,
                (int)projectiles[i].Position.Y, 2, 2); 
               // projectiles[i].Width,
               // projectiles[i].Height);

                //Determine if the two objects collided with each
                //other
                if (mainBaseRectangle.Intersects(projectileRectangle))
                {
                    station.Active = false;
                    projectiles[i].Active = false;
                    //projectiles[i].Active = false;
                    
                    //Subtract the health from the player based on
                    //the enemy damage
                    //station.base_health -= projectiles[i].Damage;

                    //Since the enemy collided with the player
                    // destroy it
                    //projectiles[i].Health = 0;

                    //If the player health is less than zero we died
                    //if (station.base_health <= 0)
                    //    station.Active = false;
                }

                for (int k = 0; k < enemies.Count; k++)
                {
                
                    enemyRectangle = new Rectangle((int)enemies[k].Position.X, (int)enemies[k].Position.Y,
                        enemies[k].Width, enemies[k].Height);

                    if (enemyRectangle.Intersects(projectileRectangle))
                    {
                        enemies[k].Active = false;
                        //projectiles[i].Active = false;
                    
                    }

                    

                }

                for (int j = 0; j < player.shieldList.Count; j++)
                {

                    
                    if (projectileRectangle.Intersects(player.shieldList[j].getRect()))
                    {
                       
                        projectiles[i].SetVelocity(Vector2.Reflect(projectiles[i].Velocity, player.shieldList[j].getNorm()));

                        

                        if (player.shieldList.ElementAt(j + 1) != null)
                                player.shieldList.RemoveAt(j + 1);
                        
                        
                        if(player.shieldList.ElementAt(j) != null)
                                player.shieldList.RemoveAt(j);

                        if (j - 1 > 0)
                        {
                            if (player.shieldList.ElementAt(j - 1) != null)
                                player.shieldList.RemoveAt(j - 1);
                        }
   
                       
                        
                        
                    }
                }




            }
        }
        #endregion
    }
}
